/*
 * Sylvain BERTRAND <digital.ragnarok@gmail.com>
 * code protected by GNU GPL v3
 */
#include <fcntl.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XKB.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/sync.h>
#include <glib.h>
#include "display.h"
#include "internal.h"
#include "keyboard.h"
#include "xqueue.h"
Display *t_display = NULL;
gboolean t_display_error_occured = FALSE;
gboolean t_display_extension_xkb = FALSE;
gint t_display_extension_xkb_basep;
gboolean t_display_extension_shape = FALSE;
gint t_display_extension_shape_basep;
gboolean t_display_extension_xinerama = FALSE;
gint t_display_extension_xinerama_basep;
gboolean t_display_extension_randr = FALSE;
gint t_display_extension_randr_basep;
gboolean t_display_extension_sync = FALSE;
gint t_display_extension_sync_basep;
static gboolean xerror_ignore = FALSE;
static gint xerror_handler(Display *d, XErrorEvent * e)
{
#	ifdef DEBUG
	gchar errtxt[128];
	XGetErrorText(d, e->error_code, errtxt, 127);
	if(!xerror_ignore) {
		if(e->error_code == BadWindow);
		else
			g_error("X Error: %s", errtxt);
	} else
		g_debug("Ignoring XError code %d '%s'", e->error_code, errtxt);
#	else
	(void)d;
	(void)e;
#	endif
	t_display_error_occured = TRUE;
	return 0;
}

gboolean t_display_open(const char *display_name)
{
	gchar *n;
	Display *d = NULL;
	n = display_name ? g_strdup(display_name) : NULL;
	t_display = d = XOpenDisplay(n);
	if(d) {
		gint junk, major, minor;
		(void)junk, (void)major, (void)minor;
		if(fcntl(ConnectionNumber(d), F_SETFD, 1) == -1)
			g_message("Failed to set display as close-on-exec");
		XSetErrorHandler(xerror_handler);
		major = XkbMajorVersion;
		minor = XkbMinorVersion;
		t_display_extension_xkb =
			XkbQueryExtension(d, &junk, &t_display_extension_xkb_basep, &junk, &major, &minor);
		if(!t_display_extension_xkb)
			g_message("XKB extension is not present on the server or too old");
		t_display_extension_shape = XShapeQueryExtension(d, &t_display_extension_shape_basep, &junk);
		if(!t_display_extension_shape)
			g_message("X Shape extension is not present on the server");
		t_display_extension_xinerama = XineramaQueryExtension(d, &t_display_extension_xinerama_basep, &junk)
			&& XineramaIsActive(d);
		if(!t_display_extension_xinerama)
			g_message("Xinerama extension is not present on the server");
		t_display_extension_randr = XRRQueryExtension(d, &t_display_extension_randr_basep, &junk);
		if(!t_display_extension_randr)
			g_message("XRandR extension is not present on the server");
		t_display_extension_sync = XSyncQueryExtension(d, &t_display_extension_sync_basep, &junk)
			&& XSyncInitialize(d, &junk, &junk);
		if(!t_display_extension_sync)
			g_message("X Sync extension is not present on the server or is an incompatible version");
		t_prop_startup();
		t_keyboard_reload();
	}
	g_free(n);
	if(t_display)
		xqueue_init();
	return t_display != NULL;
}

void t_display_close(void)
{
	t_keyboard_shutdown();
	if(t_display) {
		xqueue_destroy();
		XCloseDisplay(t_display);
	}
}

void t_display_ignore_errors(gboolean ignore)
{
	XSync(t_display, FALSE);
	xerror_ignore = ignore;
	if(ignore)
		t_display_error_occured = FALSE;
}
